/*
 *  Copyright 2004 Blandware (http://www.blandware.com)
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.blandware.atleap.persistence.hibernate.core;

import com.blandware.atleap.common.util.PartialCollection;
import com.blandware.atleap.common.util.QueryInfo;
import com.blandware.atleap.model.core.ContentField;
import com.blandware.atleap.model.core.ContentFieldValue;
import com.blandware.atleap.model.core.ContentLocale;
import com.blandware.atleap.persistence.core.ContentFieldValueDAO;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.ListIterator;

/**
 * <p>Hibernate implementation of ContentFieldValueDAO</p>
 * <p><a href="ContentFieldValueDAOHibernate.java.html"><i>View Source</i></a></p>
 *
 * @author Sergey Zubtsovskiy <a href="mailto:sergey.zubtsovskiy@blandware.com">&lt;sergey.zubtsovskiy@blandware.com&gt;</a>
 * @version $Revision: 1.26 $ $Date: 2008/06/23 13:24:53 $
 */
public class ContentFieldValueDAOHibernate extends BaseDAOHibernate implements ContentFieldValueDAO {

	/**
	 * Creates new instance of ContentFieldValueDAOHibernate
	 */
	public ContentFieldValueDAOHibernate() {
	}

	// ~ CRUD Methods ================================================================

	/**
	 * @see com.blandware.atleap.persistence.core.ContentFieldValueDAO#createContentFieldValue(com.blandware.atleap.model.core.ContentFieldValue, com.blandware.atleap.model.core.ContentField, com.blandware.atleap.model.core.ContentLocale)
	 */
	public Long createContentFieldValue(ContentFieldValue contentFieldValue, ContentField field, ContentLocale contentLocale) {
		contentFieldValue.setLastUpdatedDatetime(new Date());
		field.addContentFieldValue(contentFieldValue);
		contentFieldValue.setContentLocale(contentLocale);
		return (Long) getHibernateTemplate().save(contentFieldValue);
	}

	/**
	 * @see com.blandware.atleap.persistence.core.ContentFieldValueDAO#retrieveContentFieldValue(java.lang.Long)
	 */
	public ContentFieldValue retrieveContentFieldValue(Long contentFieldValueId) {
		return (ContentFieldValue) getHibernateTemplate().get(ContentFieldValue.class, contentFieldValueId);
	}

	/**
	 * @see com.blandware.atleap.persistence.core.ContentFieldValueDAO#updateContentFieldValue(com.blandware.atleap.model.core.ContentFieldValue, com.blandware.atleap.model.core.ContentField, com.blandware.atleap.model.core.ContentLocale)
	 */
	public void updateContentFieldValue(ContentFieldValue contentFieldValue, ContentField field, ContentLocale contentLocale) {
		contentFieldValue.setLastUpdatedDatetime(new Date());
		ContentFieldValue oldContentFieldValue = field.updateContentFieldValue(contentFieldValue);
        removeFromCache(oldContentFieldValue);
		contentFieldValue.setContentLocale(contentLocale);
		getHibernateTemplate().update(contentFieldValue);
	}

	/**
	 * @see com.blandware.atleap.persistence.core.ContentFieldValueDAO#deleteContentFieldValue(com.blandware.atleap.model.core.ContentFieldValue)
	 */
	public void deleteContentFieldValue(ContentFieldValue contentFieldValue) {
		getHibernateTemplate().delete(contentFieldValue);
		contentFieldValue.getContentField().removeContentFieldValue(contentFieldValue);
	}

	// ~ Additional methods ================================================================

	/**
	 * @see com.blandware.atleap.persistence.core.ContentFieldValueDAO#listContentFieldValues(com.blandware.atleap.common.util.QueryInfo)
	 */
	public PartialCollection listContentFieldValues(QueryInfo queryInfo) {
		String whereClause = new String();
		String orderByClause = new String();
		if ( queryInfo != null ) {
			whereClause = queryInfo.getWhereClause();
			orderByClause = queryInfo.getOrderByClause();
			if ( whereClause != null && whereClause.length() != 0 ) {
				whereClause = " and " + whereClause;
			} else {
				whereClause = new String();
			}
			if ( orderByClause != null && orderByClause.length() != 0 ) {
				orderByClause = " order by " + orderByClause;
			} else {
				orderByClause = new String();
			}
		}

		Long contentFieldId = (Long) queryInfo.getQueryParameters().get("contentFieldId");
		List list = null;
		Integer total = null;
		String hqlPart = "from ContentFieldValue c where (c.contentField.id = ?) " + whereClause;
		if ( queryInfo != null && (queryInfo.getLimit() != null || queryInfo.getOffset() != null) ) {
			String hqlForTotal = "select count(c.id) " + hqlPart;
			total = (Integer) findUniqueIntegerResult(hqlForTotal, new Object[]{contentFieldId});
			if ( total == null ) {
				total = new Integer(0);
			}
		}
        // If we don't have any info about the total number of results yet or
        // we know that there's something that will be found, then fetch data
		if ( total == null || total.intValue() > 0 ) {
			String hql = "select c.id, c.contentLocale, c.lastUpdatedDatetime " + hqlPart + orderByClause;
			list = executeFind(hql, queryInfo, new Object[]{contentFieldId});
			if ( total == null ) {
				total = new Integer(list.size());
			}
			for ( ListIterator i = list.listIterator(); i.hasNext(); ) {
				Object[] objects = (Object[]) i.next();
				ContentFieldValue contentFieldValue = new ContentFieldValue();
				contentFieldValue.setId((Long) objects[0]);
				contentFieldValue.setContentLocale((ContentLocale) objects[1]);
				contentFieldValue.setLastUpdatedDatetime((Date) objects[2]);
				i.set(contentFieldValue);
			}
		} else {
			list = new ArrayList();
		}
		return new PartialCollection(list, total);
	}

	/**
	 * @see com.blandware.atleap.persistence.core.ContentFieldValueDAO#hasDuplicates(com.blandware.atleap.model.core.ContentFieldValue, Long, String)
	 */
	public boolean hasDuplicates(ContentFieldValue contentFieldValue, Long fieldId, String localeIdentifier) {

		ArrayList args = new ArrayList();
		args.add(fieldId);
		args.add(localeIdentifier);

		String hql = "select count(c.id) from ContentFieldValue c where c.contentField.id = ? and c.contentLocale.identifier = ?";
		if ( contentFieldValue.getId() != null ) {
			hql += " and c.id != ?";
			args.add(contentFieldValue.getId());
		}

		int count = ((Integer) findUniqueIntegerResult(hql, args.toArray())).intValue();

		return count > 0;
	}

	// ~ Finders ================================================================

	/**
	 * @see com.blandware.atleap.persistence.core.ContentFieldValueDAO#findContentFieldValueByContentFieldAndLocale(com.blandware.atleap.model.core.ContentField, com.blandware.atleap.model.core.ContentLocale)
	 */
	public ContentFieldValue findContentFieldValueByContentFieldAndLocale(ContentField field, ContentLocale contentLocale) {
		return (ContentFieldValue) findUniqueResult("select c from ContentFieldValue c where c.contentField = ? and c.contentLocale = ?", new Object[]{field, contentLocale});
	}

	/**
	 * @see com.blandware.atleap.persistence.core.ContentFieldValueDAO#findContentFieldValueByUriAndIdentifierAndLocale(java.lang.String, java.lang.String, java.lang.String)
	 */
	public ContentFieldValue findContentFieldValueByUriAndIdentifierAndLocale(String uri, String identifier, String localeIdentifier) {
        String hql = "select value from Page page inner join page.contentFields field inner join field.contentFieldValues value where page.uri = ? and field.identifier = ? and value.contentLocale.identifier = ?";
		ContentFieldValue contentFieldValue = (ContentFieldValue) findUniqueResult(hql, new Object[]{uri, identifier, localeIdentifier});
		if ( contentFieldValue == null ) {
            // Try to look for CFV in default locale
            hql = "select value from Page page inner join page.contentFields field inner join field.contentFieldValues value where page.uri = ? and field.identifier = ? and value.contentLocale.defaultInstance = 'T'";
			contentFieldValue = (ContentFieldValue) findUniqueResult(hql, new Object[]{uri, identifier});
		}
		return contentFieldValue;
	}

	/**
	 * @see com.blandware.atleap.persistence.core.ContentFieldValueDAO#findContentFieldValueByDefinitionAndIdentifierAndLocale(java.lang.String, java.lang.String, java.lang.String)
	 */
	public ContentFieldValue findContentFieldValueByDefinitionAndIdentifierAndLocale(String definition, String identifier, String localeIdentifier) {
        String hql = "select value from Layout layout inner join layout.contentFields field inner join field.contentFieldValues value where layout.definition = ? and field.identifier = ? and value.contentLocale.identifier = ?";
		ContentFieldValue contentFieldValue = (ContentFieldValue) findUniqueResult(hql, new Object[]{definition, identifier, localeIdentifier});
		if ( contentFieldValue == null ) {
            // Try to look for CFV in default locale
            hql = "select value from Layout layout inner join layout.contentFields field inner join field.contentFieldValues value where layout.definition = ? and field.identifier = ? and value.contentLocale.defaultInstance = 'T'";
			contentFieldValue = (ContentFieldValue) findUniqueResult(hql, new Object[]{definition, identifier});
		}
		return contentFieldValue;
	}

    /**
     * @see com.blandware.atleap.persistence.core.ContentFieldValueDAO#findContentFieldValueByLocalizableIdAndIdentifierAndLocale(java.lang.Long, java.lang.String, java.lang.String)
     */
    public ContentFieldValue findContentFieldValueByLocalizableIdAndIdentifierAndLocale(Long localizableId, String identifier, String localeIdentifier) {
        String hql = "select value from Localizable localizable inner join localizable.contentFields field inner join field.contentFieldValues value where localizable.id = ? and field.identifier = ? and value.contentLocale.identifier = ?";
        ContentFieldValue contentFieldValue = (ContentFieldValue) findUniqueResult(hql, new Object[]{localizableId, identifier, localeIdentifier});
        if ( contentFieldValue == null ) {
            // Try to look for CFV in default locale
            hql = "select value from Localizable localizable inner join localizable.contentFields field inner join field.contentFieldValues value where localizable.id = ? and field.identifier = ? and value.contentLocale.defaultInstance = 'T'";
            contentFieldValue = (ContentFieldValue) findUniqueResult(hql, new Object[]{localizableId, identifier});
        }
        return contentFieldValue;
    }

}
